package com.lsh.streamgd.http;

import com.lsh.streamgd.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 网络访问工具类,以封装对象NetWorkContext为上下文参数,进行访问.
 * 
  * @ClassName: HttpRequest
  * @author liujingui
  * @date 2016年3月3日 下午12:34:01
  * @see NetWorkContext
 */
public class HttpRequest {

    private static final Logger logger = LoggerFactory.getLogger(HttpRequest.class);

    public static NetWorkContext.Response doReq(NetWorkContext context){
        logger.info("\n=====[ http 请求开始 ]=====\n url:{},\n pathparams:{},\n bodyparams:{}", context.getUrl(), context.getPathParams(), context.getBodyParams());
        long start = System.currentTimeMillis();
        NetWorkContext.Response response = run(context);
        long end = System.currentTimeMillis();
        logger.info("\n=====[ http 请求结束 ]=====\n time costs:{},\n response code:{},\n response body:{}", end - start, response.getCode(), response.getRespBody());
        return response;
    }

    private static NetWorkContext.Response run(NetWorkContext context){
    
        String responseString = "";
        
        String urlStr = context.getUrl();
        String method = context.getMethod();
        if(StringUtil.hasBlank(urlStr,method)){
            context.setRespCode(HttpURLConnection.HTTP_BAD_REQUEST).setRespBody("invalid request");
        }
        String pathParams = context.getPathParams();
        if(!StringUtil.isBlank(pathParams)){
            if(!urlStr.contains("?")){
                urlStr += "?" + pathParams;
            }else{
                urlStr += "&" + pathParams;
            }
        }
        HttpURLConnection conn = null;
        OutputStreamWriter out = null;
        BufferedReader in = null;
        try{
            Map innerPathParams = context.getInnerPathParams();
            if(null != innerPathParams){
                Iterator iter = innerPathParams.entrySet().iterator();
                while (iter.hasNext()) {
                    Entry entry = (Entry) iter.next();
                    String key = (String)entry.getKey();
                    String val = (String) entry.getValue();
                    urlStr = urlStr.replace("{"+key+"}", val);
                }
            }
            URL url = new URL(urlStr);
            boolean isproxy=context.isIsproxy();
            if(isproxy){//使用代理模式
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy1.wanda.cn", 8080));
                conn = (HttpURLConnection) url.openConnection(proxy);
            }else{
                conn = (HttpURLConnection) url.openConnection();
            }

            //conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod(method);
            Map<String,String> headers = context.getHeaders();
            if(null != headers){
                logger.info("\nrequest Header:");
                Iterator<Entry<String, String>> iter = headers.entrySet().iterator();
                while (iter.hasNext()) {
                    Entry entry = (Entry) iter.next();
                    String key = (String) entry.getKey();
                    String val = (String) entry.getValue();
                    conn.setRequestProperty(key, val);
                    logger.info("{}:{}",key,val);
                }
            }
            conn.setUseCaches(false);
            conn.setDoOutput(!"GET".equals(method));
            conn.setDoInput(true);
            conn.connect();
            String bodyParams = context.getBodyParams();
            if(!StringUtil.isBlank(bodyParams)){
                out = new OutputStreamWriter(conn.getOutputStream(),"utf-8");
                out.write(bodyParams);
                out.flush();
            }
            Map<String, List<String>> map = conn.getHeaderFields();
            logger.info("\nresponse Header:");
            for (String key : map.keySet()) {
                logger.info("{} : {}", key, map.get(key));
            }
            int responseCode = conn.getResponseCode();
            if(responseCode < HttpURLConnection.HTTP_BAD_REQUEST){
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
                String line;
                while ((line = in.readLine()) != null) {
                    responseString += line;
                }
            }else{
                if(null == conn.getErrorStream()){
                    responseString = "empty error response body";
                }else{
                    in = new BufferedReader(new InputStreamReader(conn.getErrorStream(),"utf-8"));
                    String line;
                    while ((line = in.readLine()) != null) {
                        responseString += line;
                    }
                }
            }
            context.setRespCode(responseCode).setRespBody(responseString);
        }catch(Exception e){
            context.setRespCode(HttpURLConnection.HTTP_INTERNAL_ERROR).setRespBody(e.getMessage());
            logger.error("\n=====[  http请求发生异常  ]=====\n{}", StringUtil.getExceptonStack(e));
        }finally{
            try{
                if(out != null){
                    out.flush();
                    out.close();
                }
                if(in != null){
                    in.close();
                }
            }catch(Exception e){
                context.setRespCode(HttpURLConnection.HTTP_INTERNAL_ERROR).setRespBody(e.getMessage());
                logger.error("\n=====[  http请求发生异常  ]=====\n{}", StringUtil.getExceptonStack(e));
            }
            if(conn != null){
                conn.disconnect();
            }
        }
        return context.getResp();
    }
}
